import { Global, Logger, Module, ValidationPipe } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';
import { buildConnectionOptions } from '../ormconfig';
import { UserModule } from '@/modules/system/user/user.module';
import { RoleModule } from '@/modules/system/role/role.module';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
import { AuthModule } from '@/modules/system/auth/auth.module';
import { JwtAuthGuard } from '@/guard/jwt-auth.guard';
import { UserRoleModule } from './modules/system/user-role/user-role.module';
import { ConfigModule as ConfigInfoModule } from '@/modules/system/config/config.module';
import { DictModule } from '@/modules/system/dict/dict.module';
import { LogModule } from '@/modules/system/log/log.module';
import { GlobalExceptionFilter } from '@/filters/global-exception.filter';
import { HttpExceptionFilter } from '@/filters/http-exception.filter';
import { ScheduleModule } from '@nestjs/schedule';
import { TasksModule } from '@/schedule/tasks.module';
import { MenuModule } from './modules/system/menu/menu.module';
import { RoleMenuModule } from './modules/system/role-menu/role-menu.module';
import { ApiModule } from './modules/system/api/api.module';
import { RoleApiModule } from './modules/system/role-api/role-api.module';
import { UserSubuserModule } from './modules/system/user-subuser/user-subuser.module';
import { OssModule } from './modules/system/oss/oss.module';
import { ServeStaticModule, ServeStaticModuleOptions } from '@nestjs/serve-static';
import path from 'path';
import { TransformInterceptor } from '@/interceptors/transform.interceptor';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

const schema = Joi.object({
  NODE_ENV: Joi.string()
    .valid('development', 'production', 'test')
    .default('development'),
  DB_PORT: Joi.number().default(3306),
  DB_HOST: Joi.alternatives().try(Joi.string().ip(), Joi.string().domain()),
  DB_TYPE: Joi.string().valid('mysql', 'postgres'),
  DB_DATABASE: Joi.string().required(),
  DB_USERNAME: Joi.string().required(),
  DB_PASSWORD: Joi.string().required(),
  DB_SYNC: Joi.boolean().default(false),
  LOG_ON: Joi.boolean(),
  LOG_LEVEL: Joi.string(),
});

import { StudentInoutMessageModule } from '@/modules/hik/student-inout-message/student-inout-message.module';

@Global()
@Module({
  imports: [
    ScheduleModule.forRoot(),
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      // https://github.com/nestjs/config/issues/209#issuecomment-625765057
      // load方法需要自己加入验证
      // 解决方法：https://dev.to/rrgt19/ways-to-validate-environment-configuration-in-a-forfeature-config-in-nestjs-2ehp
      load: [
        () => {
          const values = dotenv.config({ path: '.env' });
          const { error } = schema.validate(values?.parsed, {
            // 允许未知的环境变量
            allowUnknown: true,
            // 如果有错误，不要立即停止，而是收集所有错误
            abortEarly: false,
          });
          if (error) {
            throw new Error(
              `Validation failed - Is there an environment variable missing?
                         ${error.message}`,
            );
          }
          return values;
        },


      ],
      validationSchema: schema,
    }),
    // 服务静态化, 生产环境最好使用 nginx 做资源映射， 可以根据环境配置做区分
    ServeStaticModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => [{
        rootPath: path.join(__dirname, '../../', 'upload'),
        exclude: [`${config.get('API_PREFIX')}`],
        serveRoot: config.get('FILE_SERVE_ROOT'),
        serveStaticOptions: {
          cacheControl: true,
        },
      }] as ServeStaticModuleOptions[],
    }),
    // Redis集成
    // RedisModule.forRootAsync({
    //   useFactory: (configService: ConfigService, logger: LoggerService) => {
    //     const host = configService.get(ConfigEnum.REDIS_HOST);
    //     const port = configService.get(ConfigEnum.REDIS_PORT);
    //     const password = configService.get(ConfigEnum.REDIS_PASSWORD);
    //     const url = password
    //       ? `redis://${password}@${host}:${port}`
    //       : `redis://${host}:${port}`;
    //     return {
    //       config: {
    //         url,
    //         reconnectOnError: (err) => {
    //           logger.error(`Redis Connection error: ${err}`);
    //           return true;
    //         },
    //       },
    //     };
    //   },
    //   inject: [ConfigService, Logger],
    // }),
    TypeOrmModule.forRootAsync({
      useFactory: async () => await buildConnectionOptions(),
    }),
    UserModule,
    StudentInoutMessageModule,
    RoleModule,
    AuthModule,
    UserRoleModule,
    ConfigInfoModule,
    DictModule,
    LogModule,
    TasksModule,
    MenuModule,
    RoleMenuModule,
    ApiModule,
    RoleApiModule,
    UserSubuserModule,
    OssModule,
  ],
  controllers: [],
  providers: [
    Logger,
    //注册全局守卫
    {
      provide: APP_GUARD,
      useClass: JwtAuthGuard,
    },
    // 3. 全局管道：ValidationPipe（替代 main.ts 中的 useGlobalPipes）
    {
      provide: APP_PIPE,
      useValue: new ValidationPipe({
        transform: true,
        transformOptions: { enableImplicitConversion: true },
        whitelist: true,
      }),
    },
    // 注册全局拦截器
    {
      provide: APP_INTERCEPTOR,
      useClass: TransformInterceptor,
    },
    //注册全局过滤器
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter, //全局错误拦截
    },
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter,//全局http过滤器
    },

  ],
  // exports: [Logger],// 可选：显式导出（但全局模块的 providers 默认已全局可用）
})
export class AppModule {
}
